Penpen7のブログ

Penpen7のエンジニアブログ

小数点以下を切り上げる場合の商を求める方法【競技プログラミング】

有名な内容だと思うが、自分用にメモ

整数型同士の割り算は切り捨てられる。

a, bを整数型(a, b>0)とするとき, a/bを計算すると小数点以下は切り捨てられる。
例)
(i) a=4, b=2
4/2=2
整数型同士の計算の場合は小数点以下は切り捨てられ、2となる。
(ii)a=5, b=2
5/2=2.5
整数型同士の計算の場合は小数点以下は切り捨てられ、2となる。
通常、整数型同士の割り算は切り捨てられ、そのままだと切り上げることはできない。

切り上げるためにはどうするか?

\frac{a+b-1}{b}

を計算し、小数点以下を切り下げると、a/bの小数点以下を切り上げた結果が得られる。
a=4, b=2
(4+2-1)/2=5/2=2.5
の小数点以下を切り捨てると、2となる。
確かに4/2=2で小数点以下を切り上げると2だから合ってる。
a=5,b=2
(5+2-1)/2=6/2=3
の小数点以下を切り捨てると、3となる。
両方ともa/bの小数点以下を切り上げた結果になっている。

証明

[]をガウス記号とする。(ここでは、小数点以下を切り捨てる程度の意味)
aがbで割り切れるか割り切れないかで場合分けする。
(i) aがbで割り切れる
a=bkとおける(kは整数)。この時,

\left[\frac{a+b-1}{b}\right]=\left[\frac{bk+b-1}{b}\right]=\left[k+\left(1-\frac{1}{b}\right)\right]=k

a/b=kの小数点以下を切り上げてもkであるから、確かに合っている。
(ii) aがbで割り切れない
aをbで割った時の余りをlと置くと, a=bk+lとおける(k,lは整数, ただし, 0<l<b)。この時,

\left[\frac{a+b-1}{b}\right]=\left[\frac{bk+l-1}{b}\right]=\left[k+1+\left(1-\frac{1}{b}\right)\right]=k+1

a/b=k+l/bの小数点以下を切り上げると、kは整数部分で、l/bは小数部分であるから、確かにk+1となり結果は合っている。

実装

C++でプログラムを組み、確認した。

#include <iostream>

using namespace std;

int main(){
  int a, b;
  cin >> a >> b;

  cout << "a/b=" << a/b << endl;
  cout << "(a+b-1)/b=" << (a+b-1)/b << endl;
  return 0;
}

(i)a=4, b=2

$ ./a.out
4 2
a/b=2
(a+b-1)/b=2

(ii)a=5, b=2

$ ./a.out
5 2
a/b=2
(a+b-1)/b=3

結論

(a+b-1)/bを計算し、小数点以下を切り捨てると, a/bの小数点以下を切り上げた結果が得られる。

© Penpen7